#ifndef CH_TASK_HPP
# define CH_TASK_HPP

#ifdef DEBUG
    #include <cstdio>
    #include <iostream>
#endif

#include <string>

extern "C"{
    #include <struct_timeval.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netinet/tcp.h>
    #include <netinet/ip.h>
    #include <net/ethernet.h>
    #include <openssl/md5.h>
}

#include "thread_pool.hpp"
#include "locked_thread_safe_queue.hpp"
#include "ByteReadStream.hpp"

#define VERSION_LEN 10
#define CIPHERS_LEN 512
#define EXTS_LEN 512
#define SNI_LEN 256
#define SUPPG_LEN 128
#define SUPPFS_LEN 128
#define TICKET_LEN 512
#define JA3_LEN 1500
#define SMALL_STR_LEN 50

// 这里主机序是 小端的，把网络序的 uint16_t 转化为 主机序
#define UINT16_NTOP(data)  ( (((data) & 0xff00)>>8) + (((data) & 0x00ff)<<8) )
#define HSPL(data1, data2) ((data1) + (data2))

static const char * EMPTY_STR = "EMPTY";

static uint32_t grease_table[] = {  0x0a0a, 0x1a1a, 0x2a2a, 0x3a3a,
                                    0x4a4a, 0x5a5a, 0x6a6a, 0x7a7a,
                                    0x8a8a, 0x9a9a, 0xaaaa, 0xbaba,
                                    0xcaca, 0xdada, 0xeaea, 0xfafa};



// gcc中结构体默认是4个字节对齐，即为32的倍数。
// 这个结构体占 28 字节
struct ch_pkt_header
{
    /* data */
    uint8_t ct;          // content type
    uint16_t ver;        // TLS version
    uint16_t pl;         // TLS payload
    uint8_t hst;         // handshake type
    uint8_t hspl_1;      // handshake payload part 1
    uint16_t hspl_2;     // handshake payload part 2
    uint16_t hsver;      // handshake version
    uint64_t random_1;   // Random port 1
    uint64_t random_2;   // Random port 2
    uint64_t random_3;   // Random port 3
    uint64_t random_4;   // Random port 4
    uint8_t sidl;        // session id payload
}__attribute__((packed));


class ch_pkt{
public:
    // 数据包内容
    char * raw_data = NULL;
    // 数据包信息
    struct pcap_pkthdr pkt_info;
    // 处理完数据包后，把处理完的信息打包放入一个线程安全的队列
    
public:
    ch_pkt(const char * d, const struct pcap_pkthdr * packet_header)
    {
        #ifdef DEBUG
            std::cout << "ch_pkt()" << std::endl;
        #endif

        raw_data = new char[1500];
        for(uint32_t i = 0; i < packet_header->caplen; ++i)
            raw_data[i] = d[i];
        pkt_info.caplen = packet_header->caplen;
        pkt_info.len = packet_header->len;
        pkt_info.ts = packet_header->ts;
    }

    // 拷贝构造
    ch_pkt(const ch_pkt & other){
        raw_data = new char[1500];
        for(uint32_t i = 0; i < other.pkt_info.caplen; ++i)
            raw_data[i] = other.raw_data[i];
        // 直接赋值
        pkt_info = other.pkt_info;

        #ifdef DEBUG
            std::cout << "ch_pkt(&)" << std::endl;
        #endif
    }

    // 移动构造
    ch_pkt(ch_pkt && other){
        raw_data = other.raw_data;
        // 直接赋值
        pkt_info = other.pkt_info;
        other.raw_data = NULL;

        #ifdef DEBUG
            std::cout << "ch_pkt(&&)" << std::endl;
        #endif
    }

    // 析构
    ~ch_pkt(){
        if(raw_data != nullptr)
            delete [](raw_data);
        // delete一个空指针是没有错的
        // 但不能对同一个非空指针delete两次
        raw_data = nullptr;

        #ifdef DEBUG
            std::cout << "~ch_pkt()" << std::endl;
        #endif
    }
};

class ch_info{
public:
    std::string time;
    std::string server_ip;
    std::string client_ip;
    std::string ja3_md5;
    std::string ticket;
    std::string sni;
public:
    ch_info(char * time, char * server_ip, char * client_ip, char * ja3_md5, char * ticket, char * sni)
    : time(time), server_ip(server_ip), client_ip(client_ip), ja3_md5(ja3_md5), ticket(ticket), sni(sni) { }
};

template<typename T>
class ch_task_cap_para{
public:
    thread_pool * executor;
    thread_safe_queue<T> * queue;
public:
    ch_task_cap_para(thread_pool * executor, thread_safe_queue<T> * queue){
        this->executor = executor;
        this->queue = queue;
    }
};

// 运行抓包程序
void run_ch_task(std::shared_ptr<ch_pkt> p, thread_safe_queue<ch_info> * queue);

// 判断是不是 grease
uint32_t check_grease(uint32_t num);

#endif